{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Multiscale Terrain Analysis"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initialize Google Earth Engine "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "import ee\n",
    "import numpy as np\n",
    "import math\n",
    "import re\n",
    "\n",
    "ee.Initialize()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load Digital Elevation Model - SRTM90_V4 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "geometry = ee.Geometry.Point([-100.55, 40.71])\n",
    "elevation = ee.Image('CGIAR/SRTM90_V4').select('elevation')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Multiscale Morphometric Land Surface Parameters Computation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Compute A Matrix and It's Inverse "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### A Matrix "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_A_matrix(windowSize, cellSize):\n",
    "    \n",
    "    A = [[0 for x in range(5)] for y in range(5)]  # 5 x 5 matrix\n",
    "    \n",
    "    midCell = (windowSize - 1) / 2\n",
    "    \n",
    "    x2 = 0\n",
    "    x4 = 0\n",
    "    x2y2 = 0\n",
    "    \n",
    "    for i in range(windowSize):\n",
    "        for j in range(windowSize):\n",
    "            Xpos = (i- midCell) * cellSize\n",
    "            Ypos = (j - midCell) * cellSize\n",
    "            x2 += Xpos ** 2\n",
    "            x4 += Xpos ** 4\n",
    "            x2y2 += Xpos ** 2 * Ypos ** 2\n",
    "    \n",
    "    A[0][0] = x4\n",
    "    A[1][1] = x4\n",
    "    A[0][1] = x2y2\n",
    "    A[1][0] = x2y2\n",
    "    A[2][2] = x2y2\n",
    "    A[3][3] = x2\n",
    "    A[4][4] = x2\n",
    "    \n",
    "    return A"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define Neighborhood - Kernel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_kernel(windowSize):\n",
    "    weight_val = 1\n",
    "    weights = ee.List.repeat(ee.List.repeat(weight_val, windowSize), windowSize)\n",
    "    \n",
    "    midCell = ee.Number(windowSize).subtract(1).divide(2)\n",
    "    \n",
    "    x = midCell.multiply(-1)\n",
    "    y = midCell.multiply(-1)\n",
    "  \n",
    "    mid_row = ee.List.repeat(weight_val, midCell)\\\n",
    "        .cat([0])\\\n",
    "        .cat(ee.List.repeat(weight_val, midCell))\n",
    "  \n",
    "    weights = weights.set(midCell, mid_row)\n",
    "\n",
    "    kernel = ee.Kernel.fixed(windowSize, windowSize, weights, x, y, False) \n",
    "  \n",
    "    return kernel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "def multi_derivatives(dem, windowSize):\n",
    "    cellSize = dem.projection().nominalScale().getInfo()\n",
    "    \n",
    "    A = create_A_matrix(5, cellSize)\n",
    "    \n",
    "    A_inv = np.linalg.inv(A)\n",
    "\n",
    "    kernel = create_kernel(windowSize)\n",
    "    \n",
    "    neighs = dem.neighborhoodToBands(kernel).updateMask(dem.gt(0))\n",
    "    \n",
    "    label = neighs.bandNames().getInfo()\n",
    "    \n",
    "    Z0 = ee.Image(0).rename('Z0').updateMask(elevation.gt(0))\n",
    "    Z1 = ee.Image(0).rename('Z1').updateMask(elevation.gt(0))\n",
    "    Z2 = ee.Image(0).rename('Z2').updateMask(elevation.gt(0))\n",
    "    Z3 = ee.Image(0).rename('Z3').updateMask(elevation.gt(0))\n",
    "    Z4 = ee.Image(0).rename('Z4').updateMask(elevation.gt(0))\n",
    "\n",
    "    for r in label:\n",
    "        y = [int(s) for s in re.findall(r'-?\\d+\\.?\\d*',r)][0] * cellSize\n",
    "        x = [int(s) for s in re.findall(r'-?\\d+\\.?\\d*',r)][1] * cellSize\n",
    "        Z0 = Z0.add(neighs.select(r).subtract(dem).multiply(x ** 2))\n",
    "        Z1 = Z1.add(neighs.select(r).subtract(dem).multiply(y ** 2))\n",
    "        Z2 = Z2.add(neighs.select(r).subtract(dem).multiply(x * y))\n",
    "        Z3 = Z3.add(neighs.select(r).subtract(dem).multiply(x))\n",
    "        Z4 = Z4.add(neighs.select(r).subtract(dem).multiply(y))\n",
    "    \n",
    "    # R\n",
    "    temp = ee.Image(0).rename('temp').updateMask(dem.gt(0))\n",
    "    temp = temp.add(Z0.multiply(A_inv[0][0]))\n",
    "    temp = temp.add(Z1.multiply(A_inv[0][1]))\n",
    "    temp = temp.add(Z2.multiply(A_inv[0][2]))\n",
    "    temp = temp.add(Z3.multiply(A_inv[0][3]))\n",
    "    temp = temp.add(Z4.multiply(A_inv[0][4]))\n",
    "    \n",
    "    R = ee.Image(temp).rename('R').updateMask(dem.gt(0)) \n",
    "\n",
    "    # T\n",
    "    temp = ee.Image(0).rename('temp').updateMask(dem.gt(0))\n",
    "    temp = temp.add(Z0.multiply(A_inv[1][0]))\n",
    "    temp = temp.add(Z1.multiply(A_inv[1][1]))\n",
    "    temp = temp.add(Z2.multiply(A_inv[1][2]))\n",
    "    temp = temp.add(Z3.multiply(A_inv[1][3]))\n",
    "    temp = temp.add(Z4.multiply(A_inv[1][4]))\n",
    "\n",
    "    T = ee.Image(temp).rename('T').updateMask(dem.gt(0)) \n",
    "\n",
    "    # S\n",
    "    temp = ee.Image(0).rename('temp').updateMask(dem.gt(0))\n",
    "    temp = temp.add(Z0.multiply(A_inv[2][0]))\n",
    "    temp = temp.add(Z1.multiply(A_inv[2][1]))\n",
    "    temp = temp.add(Z2.multiply(A_inv[2][2]))\n",
    "    temp = temp.add(Z3.multiply(A_inv[2][3]))\n",
    "    temp = temp.add(Z4.multiply(A_inv[2][4]))\n",
    "\n",
    "    S = ee.Image(temp).rename('S').updateMask(dem.gt(0)) \n",
    "\n",
    "    # P\n",
    "    temp = ee.Image(0).rename('temp').updateMask(dem.gt(0))\n",
    "    temp = temp.add(Z0.multiply(A_inv[3][0]))\n",
    "    temp = temp.add(Z1.multiply(A_inv[3][1]))\n",
    "    temp = temp.add(Z2.multiply(A_inv[3][2]))\n",
    "    temp = temp.add(Z3.multiply(A_inv[3][3]))\n",
    "    temp = temp.add(Z4.multiply(A_inv[3][4]))\n",
    "\n",
    "    P = ee.Image(temp).rename('P').updateMask(dem.gt(0)) \n",
    "\n",
    "    # Q\n",
    "    temp = ee.Image(0).rename('temp').updateMask(dem.gt(0))\n",
    "    temp = temp.add(Z0.multiply(A_inv[4][0]))\n",
    "    temp = temp.add(Z1.multiply(A_inv[4][1]))\n",
    "    temp = temp.add(Z2.multiply(A_inv[4][2]))\n",
    "    temp = temp.add(Z3.multiply(A_inv[4][3]))\n",
    "    temp = temp.add(Z4.multiply(A_inv[4][4]))\n",
    "\n",
    "    Q = ee.Image(temp).rename('Q').updateMask(dem.gt(0)) \n",
    "\n",
    "    return R, T, S, P, Q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [],
   "source": [
    "R, T, S, P, Q = multi_derivatives(elevation, 5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [],
   "source": [
    "def slope(dem, windowSize):\n",
    "    \n",
    "    R, T, S, P, Q = multi_derivatives(dem, windowSize)\n",
    "    \n",
    "    gradient = ee.Image(0).expression('((p * p) + (q * q)) ** 0.5', {\n",
    "      'p': P,\n",
    "      'q': Q\n",
    "    }).rename('gradient')\n",
    "\n",
    "\n",
    "    slope = gradient.atan().multiply(180/math.pi).rename('slope')\n",
    "    \n",
    "    return slope"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [],
   "source": [
    "slope_ = slope(elevation, 5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [],
   "source": [
    "def profile(dem, windowSize):\n",
    "    \n",
    "    R, T, S, P, Q = multi_derivatives(dem, windowSize)\n",
    "    \n",
    "    prof = ee.Image(0).expression('-((p*p*r) + 2 * (p*q*s) + (q*q*t)) / (((p*p)+(q*q)) * (1+(p*p)+(q*q))** 1.5)', {\n",
    "      'p': P,\n",
    "      'q': Q,\n",
    "      's': S,\n",
    "      't': T,\n",
    "      'r': R\n",
    "    }).updateMask(dem.gt(0) and P.neq(0) and Q.neq(0)).rename('profile')\n",
    "\n",
    "    \n",
    "    return prof"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [],
   "source": [
    "prof_ = profile(elevation, 5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgCiAgICAgICAgPHNjcmlwdD4KICAgICAgICAgICAgTF9OT19UT1VDSCA9IGZhbHNlOwogICAgICAgICAgICBMX0RJU0FCTEVfM0QgPSBmYWxzZTsKICAgICAgICA8L3NjcmlwdD4KICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY29kZS5qcXVlcnkuY29tL2pxdWVyeS0xLjEyLjQubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9qcy9ib290c3RyYXAubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5qcyI+PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vYm9vdHN0cmFwLzMuMi4wL2Nzcy9ib290c3RyYXAubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLXRoZW1lLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9mb250LWF3ZXNvbWUvNC42LjMvY3NzL2ZvbnQtYXdlc29tZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL0xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLzIuMC4yL2xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL3Jhd2Nkbi5naXRoYWNrLmNvbS9weXRob24tdmlzdWFsaXphdGlvbi9mb2xpdW0vbWFzdGVyL2ZvbGl1bS90ZW1wbGF0ZXMvbGVhZmxldC5hd2Vzb21lLnJvdGF0ZS5jc3MiLz4KICAgIDxzdHlsZT5odG1sLCBib2R5IHt3aWR0aDogMTAwJTtoZWlnaHQ6IDEwMCU7bWFyZ2luOiAwO3BhZGRpbmc6IDA7fTwvc3R5bGU+CiAgICA8c3R5bGU+I21hcCB7cG9zaXRpb246YWJzb2x1dGU7dG9wOjA7Ym90dG9tOjA7cmlnaHQ6MDtsZWZ0OjA7fTwvc3R5bGU+CiAgICAKICAgICAgICAgICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwKICAgICAgICAgICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgICAgICAgICAgPHN0eWxlPgogICAgICAgICAgICAgICAgI21hcF9kOTBiMTVkMzczMjc0OWI4YWE2NzgxMTliNGVjOGJiZSB7CiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOwogICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgbGVmdDogMC4wJTsKICAgICAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfZDkwYjE1ZDM3MzI3NDliOGFhNjc4MTE5YjRlYzhiYmUiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAogICAgICAgICAgICB2YXIgbWFwX2Q5MGIxNWQzNzMyNzQ5YjhhYTY3ODExOWI0ZWM4YmJlID0gTC5tYXAoCiAgICAgICAgICAgICAgICAibWFwX2Q5MGIxNWQzNzMyNzQ5YjhhYTY3ODExOWI0ZWM4YmJlIiwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjZW50ZXI6IFs0MC43MSwgLTEwMC41NV0sCiAgICAgICAgICAgICAgICAgICAgY3JzOiBMLkNSUy5FUFNHMzg1NywKICAgICAgICAgICAgICAgICAgICB6b29tOiAxMCwKICAgICAgICAgICAgICAgICAgICB6b29tQ29udHJvbDogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICBwcmVmZXJDYW52YXM6IGZhbHNlLAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICApOwoKICAgICAgICAgICAgCgogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciB0aWxlX2xheWVyXzMyMWUzMmNlMWMzZDRjNzU5NGI2ZmU0ODVjNzJhNzA3ID0gTC50aWxlTGF5ZXIoCiAgICAgICAgICAgICAgICAiaHR0cHM6Ly97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmciLAogICAgICAgICAgICAgICAgeyJhdHRyaWJ1dGlvbiI6ICJEYXRhIGJ5IFx1MDAyNmNvcHk7IFx1MDAzY2EgaHJlZj1cImh0dHA6Ly9vcGVuc3RyZWV0bWFwLm9yZ1wiXHUwMDNlT3BlblN0cmVldE1hcFx1MDAzYy9hXHUwMDNlLCB1bmRlciBcdTAwM2NhIGhyZWY9XCJodHRwOi8vd3d3Lm9wZW5zdHJlZXRtYXAub3JnL2NvcHlyaWdodFwiXHUwMDNlT0RiTFx1MDAzYy9hXHUwMDNlLiIsICJkZXRlY3RSZXRpbmEiOiBmYWxzZSwgIm1heE5hdGl2ZVpvb20iOiAxOCwgIm1heFpvb20iOiAxOCwgIm1pblpvb20iOiAwLCAibm9XcmFwIjogZmFsc2UsICJvcGFjaXR5IjogMSwgInN1YmRvbWFpbnMiOiAiYWJjIiwgInRtcyI6IGZhbHNlfQogICAgICAgICAgICApLmFkZFRvKG1hcF9kOTBiMTVkMzczMjc0OWI4YWE2NzgxMTliNGVjOGJiZSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHRpbGVfbGF5ZXJfMTc0OWZhNWJmZjY0NDkxNGFkNmJmOTQ4MDNkODdiNTkgPSBMLnRpbGVMYXllcigKICAgICAgICAgICAgICAgICJodHRwczovL2VhcnRoZW5naW5lLmdvb2dsZWFwaXMuY29tL3YxYWxwaGEvcHJvamVjdHMvZWFydGhlbmdpbmUtbGVnYWN5L21hcHMvYWVkMzNiYTFkNGQ3ZGNjMjJiNjM0M2RhMWFhMjBiZmEtODBhNWUyN2QzNjZlZWVkZTg2NTQ2YTUwNmYyMmQ2ZTAvdGlsZXMve3p9L3t4fS97eX0iLAogICAgICAgICAgICAgICAgeyJhdHRyaWJ1dGlvbiI6ICJNYXAgRGF0YSBcdTAwMjZjb3B5OyBcdTAwM2NhIGhyZWY9XCJodHRwczovL2VhcnRoZW5naW5lLmdvb2dsZS5jb20vXCJcdTAwM2VHb29nbGUgRWFydGggRW5naW5lXHUwMDNjL2FcdTAwM2UiLCAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsICJtYXhOYXRpdmVab29tIjogMTgsICJtYXhab29tIjogMTgsICJtaW5ab29tIjogMCwgIm5vV3JhcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzdWJkb21haW5zIjogImFiYyIsICJ0bXMiOiBmYWxzZX0KICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDkwYjE1ZDM3MzI3NDliOGFhNjc4MTE5YjRlYzhiYmUpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciB0aWxlX2xheWVyXzNmNzJmMGYxNTJlYzRkOTU4Zjg5MmE4ZmFhNDAzMDc4ID0gTC50aWxlTGF5ZXIoCiAgICAgICAgICAgICAgICAiaHR0cHM6Ly9lYXJ0aGVuZ2luZS5nb29nbGVhcGlzLmNvbS92MWFscGhhL3Byb2plY3RzL2VhcnRoZW5naW5lLWxlZ2FjeS9tYXBzLzAzZWZjMzlkMjgyMjVhZDVkNzIwMzYzOGJjNThlMmRmLTM0NmMyZmJlNWJhZGFlMWE1MmViZjgxY2Y4N2M0N2U0L3RpbGVzL3t6fS97eH0ve3l9IiwKICAgICAgICAgICAgICAgIHsiYXR0cmlidXRpb24iOiAiTWFwIERhdGEgXHUwMDI2Y29weTsgXHUwMDNjYSBocmVmPVwiaHR0cHM6Ly9lYXJ0aGVuZ2luZS5nb29nbGUuY29tL1wiXHUwMDNlR29vZ2xlIEVhcnRoIEVuZ2luZVx1MDAzYy9hXHUwMDNlIiwgImRldGVjdFJldGluYSI6IGZhbHNlLCAibWF4TmF0aXZlWm9vbSI6IDE4LCAibWF4Wm9vbSI6IDE4LCAibWluWm9vbSI6IDAsICJub1dyYXAiOiBmYWxzZSwgIm9wYWNpdHkiOiAxLCAic3ViZG9tYWlucyI6ICJhYmMiLCAidG1zIjogZmFsc2V9CiAgICAgICAgICAgICkuYWRkVG8obWFwX2Q5MGIxNWQzNzMyNzQ5YjhhYTY3ODExOWI0ZWM4YmJlKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgbGF5ZXJfY29udHJvbF9iNDgwNjExNDYwYmM0MTU5YTI5YzA4YzA4OTg5MWE4MCA9IHsKICAgICAgICAgICAgICAgIGJhc2VfbGF5ZXJzIDogewogICAgICAgICAgICAgICAgICAgICJvcGVuc3RyZWV0bWFwIiA6IHRpbGVfbGF5ZXJfMzIxZTMyY2UxYzNkNGM3NTk0YjZmZTQ4NWM3MmE3MDcsCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgb3ZlcmxheXMgOiAgewogICAgICAgICAgICAgICAgICAgICJzbG9wZSIgOiB0aWxlX2xheWVyXzE3NDlmYTViZmY2NDQ5MTRhZDZiZjk0ODAzZDg3YjU5LAogICAgICAgICAgICAgICAgICAgICJwcm9maWxlIiA6IHRpbGVfbGF5ZXJfM2Y3MmYwZjE1MmVjNGQ5NThmODkyYThmYWE0MDMwNzgsCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICB9OwogICAgICAgICAgICBMLmNvbnRyb2wubGF5ZXJzKAogICAgICAgICAgICAgICAgbGF5ZXJfY29udHJvbF9iNDgwNjExNDYwYmM0MTU5YTI5YzA4YzA4OTg5MWE4MC5iYXNlX2xheWVycywKICAgICAgICAgICAgICAgIGxheWVyX2NvbnRyb2xfYjQ4MDYxMTQ2MGJjNDE1OWEyOWMwOGMwODk4OTFhODAub3ZlcmxheXMsCiAgICAgICAgICAgICAgICB7ImF1dG9aSW5kZXgiOiB0cnVlLCAiY29sbGFwc2VkIjogdHJ1ZSwgInBvc2l0aW9uIjogInRvcHJpZ2h0In0KICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDkwYjE1ZDM3MzI3NDliOGFhNjc4MTE5YjRlYzhiYmUpOwogICAgICAgIAo8L3NjcmlwdD4=\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x7fd7cebee070>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Import the Folium library.\n",
    "import folium\n",
    "\n",
    "# Define a method for displaying Earth Engine image tiles to folium map.\n",
    "def add_ee_layer(self, ee_image_object, vis_params, name):\n",
    "  map_id_dict = ee.Image(ee_image_object).getMapId(vis_params)\n",
    "  folium.raster_layers.TileLayer(\n",
    "    tiles = map_id_dict['tile_fetcher'].url_format,\n",
    "    attr = 'Map Data &copy; <a href=\"https://earthengine.google.com/\">Google Earth Engine</a>',\n",
    "    name = name,\n",
    "    overlay = True,\n",
    "    control = True\n",
    "  ).add_to(self)\n",
    "\n",
    "# Add EE drawing method to folium.\n",
    "folium.Map.add_ee_layer = add_ee_layer\n",
    "\n",
    "# Set visualization parameters.\n",
    "Viz_slope = {'min': 0, 'max': 90, 'palette': ['Green', 'Yellow','Red']}\n",
    "Viz_prof = {'min': -0.001, 'max': 0.001,'palette': ['Red', 'White','Blue']};\n",
    "\n",
    "\n",
    "# Create a folium map object.\n",
    "my_map = folium.Map(location=[40.71, -100.55])\n",
    "\n",
    "# Add the elevation model to the map object.\n",
    "#my_map.add_ee_layer(elevation.updateMask(elevation.gt(0)), {'min':0, 'max':4000}, 'DEM')\n",
    "my_map.add_ee_layer(slope_, Viz_slope, 'slope')\n",
    "my_map.add_ee_layer(prof_, Viz_prof, 'profile')\n",
    "\n",
    "\n",
    "# Add a layer control panel to the map.\n",
    "my_map.add_child(folium.LayerControl())\n",
    "\n",
    "# Display the map.\n",
    "display(my_map)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-1.9366680759475603e-05\n"
     ]
    }
   ],
   "source": [
    "geometry1 = ee.Geometry.Point([-100.55, 40.71])\n",
    "\n",
    "print(prof_.sample(geometry1, 30).first().get('profile').getInfo())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
